/***************************************************************************

  machine.c

  Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
  I/O ports)

***************************************************************************/

#include "driver.h"


/*Creation date: 98-02-18 */
/*  A few words of comment:
**
**   Whats inside of this file is a PAL16r6 emulator. Maybe someday we will
**need to use it for some other game too. We will need to make it more exact
**then (some of the functionality of this chip IS NOT implemented). However I
**have bought a book about PAL's and I'm able to make it work better.
**					Jarek Burczynski
**					s0246@goblin.pjwstk.waw.pl
*/

unsigned char andmap[64];
/*table holds outputs of all AND's (after AND map)*/

unsigned char columnvalue[32];
/*table holds inputs (ie. not x, x, not q, q) to the AND map*/

unsigned char outvalue[8];
/*8 output pins*/

unsigned char fusemap[64*32]=
{
/*		64 rows x 32 columns
**  1 - fuse blown (disconnected from input (equal to 1) )
**  0 - fuse not blown (connected to input (ie. not x, x, not q, q accordingly)
*/
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,0,1,1,0,1,1,1,0,1,1,1,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,0,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,
1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,
1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,
1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,
1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,
1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,
1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,
1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,
1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,
1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};


void update_pal(void)
{
unsigned short rowoffs;
unsigned char row, column, val;

/*count all rows AND's*/
	for (row=0; row<64; row++)
	{
		rowoffs = row<<5;
		val = 1; /*prepare for AND */
		for (column=0; column<32; column++)
		{
			if ( fusemap[ rowoffs + column ] == 0 )
				val &= columnvalue[column];
		}
		andmap[row] = val;
	}

/* I/O pin #19 */
	val=0; /*prepare for OR*/
	for (row=1; row<8; row++)
		val |= andmap[row];
	if (andmap[0]==1)
	{
		columnvalue[2]=1-val;
		columnvalue[3]=val;
		outvalue[0]=1-val;
	}
	else
	{
		//pin is in INPUT configuration so it doesn't create output...
		columnvalue[2]=0;
		columnvalue[3]=1;
	}

/* O pin #18 (D1) */
	val=0; /*prepare for OR*/
	for (row=8; row<16; row++)
		val |= andmap[row];
	columnvalue[6]=1-val;
	columnvalue[7]=val;
	outvalue[1]=1-val;

/* O pin #17 (D2) */
	val=0; /*prepare for OR*/
	for (row=16; row<24; row++)
		val |= andmap[row];
	columnvalue[10]=1-val;
	columnvalue[11]=val;
	outvalue[2]=1-val;

/* O pin #16 (D3) */
	val=0; /*prepare for OR*/
	for (row=24; row<32; row++)
		val |= andmap[row];
	columnvalue[14]=1-val;
	columnvalue[15]=val;
	outvalue[3]=1-val;

/* O pin #15 (D4) */
	val=0; /*prepare for OR*/
	for (row=32; row<40; row++)
		val |= andmap[row];
	columnvalue[18]=1-val;
	columnvalue[19]=val;
	outvalue[4]=1-val;

/* O pin #14 (D5) */
	val=0; /*prepare for OR*/
	for (row=40; row<48; row++)
		val |= andmap[row];
	columnvalue[22]=1-val;
	columnvalue[23]=val;
	outvalue[5]=1-val;

/* O pin #13 (D6) */
	val=0; /*prepare for OR*/
	for (row=48; row<56; row++)
		val |= andmap[row];
	columnvalue[26]=1-val;
	columnvalue[27]=val;
	outvalue[6]=1-val;

/* I/O pin #12 */
	val=0; /*prepare for OR*/
	for (row=57; row<64; row++)
		val |= andmap[row];
	if (andmap[56]==1)
	{
		columnvalue[30]=1-val;
		columnvalue[31]=val;
		outvalue[7]=1-val;
	}
	else
	{
		//pin is in INPUT configuration so it doesn't create output...
		columnvalue[30]=0;
		columnvalue[31]=1;
	}

}

WRITE_HANDLER( bagman_pal16r6_w )
{
unsigned char line;

	line = offset<<2;
	columnvalue[line] = 1-(data&1);
	columnvalue[line+1] = data&1;
}

void bagman_machine_init(void)
{
	bagman_pal16r6_w(0,1);
	bagman_pal16r6_w(1,1);
	bagman_pal16r6_w(2,1);
	bagman_pal16r6_w(3,1);
	bagman_pal16r6_w(4,1);
	bagman_pal16r6_w(5,1);
	bagman_pal16r6_w(6,1);
	bagman_pal16r6_w(7,1);
	update_pal();
}

READ_HANDLER( bagman_pal16r6_r )
{
	update_pal();
	return	(outvalue[6]) + (outvalue[5]<<1) + (outvalue[4]<<2) +
		(outvalue[3]<<3) + (outvalue[2]<<4) + (outvalue[1]<<5);

/* Notice that I haven't had Bagman schematics so this is my attemp to guess
what pin is connected to what bit in this address (a000), however it seems to
work.*/
}
